﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RPGProject.IOBuffers
{
    /// <summary>
    /// A class to handle updating a console window, without clearing the entire console each time, only keeps track of self rendering, and not another OutputBuffers
    /// </summary>
    class OutputBuffer
    {
        private CharInfo[][] array;
        public String enterLine;
        public readonly bool addWriter;
        public readonly int width;
        public readonly int height;
        public readonly CharInfo defaultCharInfo;

        /// <summary>
        /// Initializes a OutputBuffer with parameters as specified.
        /// </summary>
        /// <param name="width">The width of the Console window.</param>
        /// <param name="height">The height of the Console window.</param>
        /// <param name="defaultCharInfo">The default info for characters.</param>
        /// <param name="addWriter">Whether to have a writer location or not.</param>
        public OutputBuffer(int width, int height, CharInfo defaultCharInfo, bool addWriter = true)
        {
            this.addWriter = addWriter;
            this.defaultCharInfo = defaultCharInfo;
            this.width = width;
            this.height = height;
            this.enterLine = "";
            // array initialization to width x height
            this.array = new CharInfo[width][];
            for (int i = 0; i < this.width; i++ )
            {
                this.array[i] = new CharInfo[this.height];
                for (int j = 0; j < this.height; j++ )
                {
                    this.array[i][j] = new CharInfo(defaultCharInfo);
                }
            }
        }
        /// <summary>
        /// Gets and sets the CharInfo array at (x, y)
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public CharInfo this [int x, int y]
        {
            get
            {
                return this.array[x][y];
            }
            set
            {
                if(this.array[x][y] != value)
                    this.array[x][y] = new CharInfo(value);
            }
        }
        /// <summary>
        /// Renders the buffer to the screen.
        /// </summary>
        /// <param name="forceRender">Forces the buffer to rerender everything.</param>
        public void Render(bool forceRender = false)
        {
            this.RenderTo(0, 0, true, forceRender);
        }
        /// <summary>
        /// Renders the buffer to a specific (x, y) in Cartesian coordinates.
        /// </summary>
        /// <param name="startX">The starting x position to render to.</param>
        /// <param name="startY">The starting y position to render to.</param>
        /// <param name="solo">Makes the buffer set the console to its size.</param>
        /// <param name="forceRender">Forces the buffer to rerender everything.</param>
        public virtual void RenderTo(int startX, int startY, bool solo, bool forceRender)
        {
            Console.CursorVisible = false;
            // Changes the console size
            if (solo)
            {
                Console.WindowWidth = this.width + startX;
                Console.WindowHeight = this.height + 1 + startY;
            }
            // Renders the characters, if they havent been rendered, or if forceRender is set.
            for (int x = 0; x < this.width; x++ )
            {
                for (int y = 0; y < this.height; y++ )
                {
                    if (!this.array[x][y].IsRendered() || forceRender)
                    {
                        Console.SetCursorPosition(x + startX, y + startY);
                        this.array[x][y].Render();
                    }
                }
            }
            Console.SetCursorPosition(startX, this.height + startY);
            //Adds a little pointer line, indicating where input text will go.
            if (addWriter)
            {
                Console.BackgroundColor = ConsoleColor.Black;
                Console.ForegroundColor = ConsoleColor.White;
                Console.Write("> ");
                for (int x = 2; x < this.width - 1; x++)
                {
                    
                    Console.Write(" ");
                }
                Console.SetCursorPosition(2 + startX, this.height + startY);
            }
            Console.CursorVisible = true;
        }
    }
}
